<template>
  <div>
    <!-- 人际关系图 -->
    <p class="legend-box">
      <span><i></i>机构</span>
      <span><i></i>企业</span>
      <span><i></i>人物</span>
    </p>
    <div id="chartFour"></div>
    <!-- 提示框 -->
    <div
      class="g6-tooltip tooltip-box"
      :style="{ top: clientY + 'px', left: clientX + 'px' }"
      @mouseenter="tooltipMouseEnter"
      @mouseleave="tooltipMouseLeave"
    >
      <template v-if="showTooltip === 'node'">
        <div class="tip-box">
          {{ toolTipNodeModel && toolTipNodeModel.label }}
        </div>
      </template>
      <template v-else-if="showTooltip === 'edge'">
        <ul class="list-box" :class="{ maxHeight: this.ipi > 1 }">
          <li class="theader">
            <span>申请日</span>
            <span>专利号</span>
            <span>科研成果</span>
          </li>
          <li
            v-for="(item, index) in toolTipEdgeModel"
            :key="index"
            class="tbody"
          >
            <span>{{ item.ad }}</span>
            <span>{{ item.pn }}</span>
            <span>{{ item.title }}</span>
          </li>
        </ul>
        <el-pagination
          background
          layout="prev, pager, next"
          :total="total"
          :page-size="ips"
          :current-page.sync="ipi"
          @current-change="getCurrentPage"
          class="elpagination"
        >
        </el-pagination>
      </template>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    info: {
      type: Object,
    },
  },
  data() {
    return {
      graph: null,
      chartData: {
        nodes: [],
        edges: [],
      },
      scrollWidth: 0,
      scrollHeight: 0,
      rootNodeWidth: 109,
      rootNodeHeight: 109,
      ipi: 1,
      ips: 6,
      total: 0,
      showTooltip: false,
      toolTipHidden: false,
      toolTipHiddenTimeout: null,
      clientX: -9999,
      clientY: -9999,
      toolTipNodeModel: {},
      toolTipEdgeModel: [],
      toolTipEdgeAllModel: [],
    };
  },
  methods: {
    init() {
      this.scrollWidth = document.getElementById("chartFour").scrollWidth;
      this.scrollHeight = document.getElementById("chartFour").scrollHeight;
      this.initrG6();
    },
    // 自定义节点
    initrG6() {
      // 中心节点
      G6.registerNode(
        "rootNode",
        {
          draw(cfg, group) {
            const width = 109;
            const height = 109;
            const mWidth = 55;
            const mHeight = 55;
            const style = cfg.style;

            const keyShape = group.addShape("circle", {
              attrs: {
                ...style,
                x: width / 2,
                y: height / 2,
                r: width / 2,
              },
              name: "rootKeyShape",
              draggable: true,
            });

            const circleImg1 = group.addShape("image", {
              attrs: {
                width,
                height,
                img:
                  "",
              },
              name: "circleImg1",
              draggable: true,
            });

            const circleImg2 = group.addShape("image", {
              attrs: {
                width: mWidth,
                height: mHeight,
                x: (width - mWidth) / 2,
                y: (height - mHeight) / 2,
                img:
                  "",
              },
              name: "circleImg2",
              draggable: true,
            });

            const content =
              cfg.label && cfg.label.length > 12
                ? cfg.label.substr(0, 10) + "..."
                : cfg.label;
            const text = group.addShape("text", {
              attrs: {
                textAlign: "center",
                textBaseline: "top",
                text: content,
                x: width / 2,
                y: height + 10,
                fill: "#2f41c8",
                fontSize: 22,
                fontWeight: "bold",
                textAlign: "center",
                lineHeight: 20,
              },
              name: "rootTextShape",
              draggable: true,
            });

            return keyShape;
          },
        },
        "circle"
      );

      // 子节点
      G6.registerNode(
        "childNode",
        {
          draw(cfg, group) {
            let width = 31;
            let height = 31;
            const style = cfg.style;

            let imgData = "";
            if (cfg.dataType === "机构") {
              // 机构
              imgData =
                "";
            } else if (cfg.dataType === "企业") {
              // 企业
              imgData =
                "";
            } else if (cfg.dataType === "人物") {
              // 人物
              width = 20;
              height = 20;
              imgData =
                "";
            }

            const keyShape = group.addShape("circle", {
              attrs: {
                ...style,
                x: width / 2,
                y: height / 2,
              },
              name: "childNodeKeyShape",
              draggable: true,
            });

            // 公司图标
            const circleImg1 = group.addShape("image", {
              attrs: {
                width,
                height,
                img: imgData,
              },
              name: "circleImg1",
              draggable: true,
            });

            let content =
              cfg.label && cfg.label.length > 12
                ? cfg.label.substr(0, 10) + "..."
                : cfg.label;
            let text1Y = height + 10;
            const text1 = group.addShape("text", {
              attrs: {
                textAlign: "center",
                textBaseline: "top",
                text: content,
                x: width / 2,
                y: text1Y,
                fill: "#333",
                fontSize: 14,
                textAlign: "center",
                lineHeight: 16,
              },
              name: "childNodeTextShape1",
              draggable: true,
            });

            return keyShape;
          },
        },
        "circle"
      );

      // 连线
      G6.registerEdge(
        "flowLine",
        {
          // 响应状态变化
          setState(name, value, item) {
            const group = item.getContainer();
            const shape = group.get("children")[0]; // 顺序根据 draw 时确定
            if (value) {
              shape.attr({
                lineWidth: 3,
                stroke: "#405bda",
              });
            } else {
              shape.attr({
                lineWidth: 3,
                stroke: "#c8c4e6",
              });
            }
          },
          // update这里的设置非常重要，必须要写
          update: undefined,
        },
        "line"
      );
    },
    getChartData() {
      this.$post(this.$Url.team.talentsCooperate, {
        musts: {
          date_sort: "1",
          "in2id.id": this.info.key,
        },
        aggs: [
          {
            type: "base",
            size: "50",
            field: "an",
          },
          {
            type: "base",
            size: "50",
            field: "in2id.name",
          },
        ],
      })
        .then((res) => {
          let data = res.data;
          let nodes = [
            // 中心节点
            {
              id: this.info.name,
              label: this.info.name,
              type: "rootNode",
              x: (this.scrollWidth - this.rootNodeWidth) / 2,
              y: (this.scrollHeight - this.rootNodeHeight) / 2,
            },
            // 任职
            {
              id: data.job.key,
              label: data.job.key,
              type: "childNode",
              dataType: data.job.type,
            },
          ];

          let edges = [
            {
              source: this.info.name,
              target: data.job.key,
              targetType: data.job.type,
              label: "任职",
            },
          ];

          data.cooperation.forEach((v) => {
            nodes.push({
              id: v.key,
              label: v.key,
              type: "childNode",
              dataType: v.type,
            });
            if (v.key !== this.info.name) {
              edges.push({
                source: this.info.name,
                target: v.key,
                targetType: v.type,
                label: "合作",
              });
            }
          });

          let chartData = {
            nodes,
            edges,
          };

          this.renderChart(chartData);
        })
        .catch((err) => {});
    },
    renderChart(chartData) {
      let graph = new G6.Graph({
        container: "chartFour",
        width: this.scrollWidth,
        height: this.scrollHeight,
        // plugins: [tooltip],
        // layout: {
        //   type: 'force',
        //   linkDistance: (param) => {
        //     let x = param.target.x
        //     let y = param.target.y
        //     let distance = 280
        //     // if (x <= this.scrollWidth / 3 || x >= this.scrollWidth * (2/3)) {
        //     //   distance = 450
        //     // }
        //     return distance
        //   },
        //   // linkDistance: 100,
        //   nodeSize: [109, 60],
        //   preventOverlap: true,
        //   // clustering: true,
        //   // type: 'fruchterman',
        //   // gravity: 10,
        //   // speed: 10,
        //   // clustering: true,
        //   // clusterGravity: 50,
        //   // gravity: 1,              // 可选
        //   // speed: 5,                 // 可选
        //   // clustering: false,         // 可选
        //   // clusterGravity: 10,       // 可选
        //   // maxIteration: 2000,       // 可选，迭代次数
        //   // workerEnabled: true       // 可选，开启 web-worker  }
        // },
        modes: {
          default: ["drag-canvas", "drag-node", "zoom-canvas"],
        },
        defaultNode: {
          type: "rootNode",
        },
        defaultEdge: {
          type: "flowLine",
          style: {
            lineWidth: 2,
            lineAppendWidth: 3,
            stroke: "#03B38C",
            lineDash: [3],
          },
          labelCfg: {
            autoRotate: false,
            style: {
              fontWeight: "normal",
              fontSize: 12,
            },
          },
        },
        animate: true,
      });

      //
      let newNodes = [];
      chartData.nodes.forEach((v) => {
        if (v.type !== "rootNode") {
          newNodes.push(v);
        }
      });
      let newEdges = chartData.edges;
      const subForceLayout = new G6.Layout.force({
        center: [
          chartData.nodes[0].x + this.rootNodeWidth / 2,
          chartData.nodes[0].y + 40,
        ],
        preventOverlap: true,
        nodeSize: [109, 60],
        linkDistance: (param) => {
          let x = param.target.x;
          let y = param.target.y;
          let distance = this.scrollHeight / 3;
          // if (x <= this.scrollWidth / 3 || x >= this.scrollWidth * (2/3)) {
          //   distance = this.scrollHeight / 3 + 50
          // }
          return distance;
        },
        // nodeSize: [109, 60],
        tick: function tick() {
          // the tick function to show the animation of layout process
          graph.refreshPositions();
        },
      });
      subForceLayout.init({
        nodes: newNodes,
        edges: newEdges,
      });
      subForceLayout.execute();

      graph.read(chartData);

      this.graph = graph;

      // node事件
      graph.on("node:mouseenter", (ev) => {
        const node = ev.item;
        const model = node.getModel();
        this.clientX = ev.x;
        this.clientY = ev.y;

        this.toolTipNodeModel = model;
        this.showTooltip = "node";
        this.toolTipHidden = false;
      });

      graph.on("node:mousemove", (ev) => {
        this.clientX = ev.x;
        this.clientY = ev.y;
      });

      graph.on("node:mouseleave", (ev) => {
        this.toolTipHidden = true;
      });

      // edge事件
      graph.on("edge:mouseenter", (ev) => {
        const edge = ev.item;
        const model = edge.getModel();
        let name = "color" + model.dataType;
        // graph.setItemState(edge, name, true);

        this.ipi = 1;

        if (!model.result) {
          this.getTalentsCooperateList(model, (result) => {
            model.result = result;
            this.toolTipEdgeAllModel = result;
            this.toolTipEdgeModel = result.slice(0, this.ipi * this.ips);
            this.total = result.length;
          });
        } else {
          this.toolTipEdgeAllModel = model.result;
          this.toolTipEdgeModel = model.result.slice(0, this.ipi * this.ips);
          this.total = model.result.length;
        }

        this.clientX = ev.x;
        this.clientY = ev.y;

        this.showTooltip = "edge";
        this.toolTipHidden = false;
      });

      graph.on("edge:mousemove", (ev) => {
        this.clientX = ev.x;
        this.clientY = ev.y;
      });

      graph.on("edge:mouseleave", (ev) => {
        const edge = ev.item;
        const model = edge.getModel();
        let name = "color" + model.dataType;
        graph.setItemState(edge, name, false);

        this.toolTipHidden = true;
      });
    },
    // 获取关系
    getTalentsCooperateList(model, func) {
      let type = model.targetType;
      let param = {
        musts: {
          date_sort: "1",
          "in2id.id": this.info.key,
        },
        source: ["ad", "title", "pn"],
      };

      if (type !== "人物") {
        param["musts"]["an"] = model.target;
      } else {
        param["musts"]["in2id.name"] = model.target;
      }

      this.$post(this.$Url.team.talentsCooperateList, param)
        .then((res) => {
          let data = res.data;
          let result = (data && data.result) || [];
          func && func(result);
        })
        .catch((err) => {});
    },
    getCurrentPage(val) {
      this.ipi = val;
      this.toolTipEdgeModel = this.toolTipEdgeAllModel.slice(
        (this.ipi - 1) * this.ips,
        this.ipi * this.ips
      );
    },
    tooltipMouseEnter(e) {},
    tooltipMouseLeave(e) {},
  },
  watch: {
    info() {
      if (!this.graph) {
        this.init();
        this.getChartData();
      }
    },
    toolTipHidden() {
      if (this.toolTipHidden) {
        if (this.toolTipHiddenTimeout) {
          clearTimeout(this.toolTipHiddenTimeout);
          this.toolTipHiddenTimeout = null;
        } else {
          this.toolTipHiddenTimeout = setTimeout(() => {
            this.showTooltip = false;
            this.toolTipHidden = false;
            this.toolTipHiddenTimeout = null;
          }, 300);
        }
      } else {
        if (this.toolTipHiddenTimeout) {
          clearTimeout(this.toolTipHiddenTimeout);
          this.toolTipHiddenTimeout = null;
        }
      }
    },
  },
  mounted() {},
};
</script>

<style lang="scss" scoped>
#chartFour {
  width: 100%;
  height: 650px;
}
.legend-box {
  position: relative;
  display: inline-block;
  margin-left: 23px;
  span {
    display: inline-flex;
    margin-right: 50px;
    font-size: 14px;
    color: $mainColor;
    &:nth-child(1) {
      i {
        background-image: url("");
      }
    }
    &:nth-child(2) {
      i {
        background-image: url("");
      }
    }
    &:nth-child(3) {
      i {
        background-image: url("");
      }
    }
    i {
      display: block;
      width: 20px;
      height: 20px;
      margin-right: 20px;
      background-position: center center;
      background-size: 100% 100%;
      background-repeat: no-repeat;
    }
  }
}

.list-box {
  position: relative;
  width: 650px;
  padding: 0 21px;
  &.maxHeight {
    height: 309px;
  }
  li {
    position: relative;
    display: flex;
    // padding: 0 22px;
    list-style: none;
    color: #7674a3;
    span {
      flex: 1;
      padding-left: 4px;
      padding-right: 4px;
      font-size: 14px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
  .theader {
    line-height: 44px;
    border-bottom: 1px solid #f0f0fb;
    span {
      font-weight: bold;
      color: #2d3a86;
    }
  }
  .tbody {
    line-height: 18px;
    padding-top: 13px;
    padding-bottom: 13px;
    // &:hover {
    //   box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
    //   color: $mainColor;
    //   cursor: pointer;
    // }
  }
}
.elpagination {
  margin-top: 10px;
  margin-bottom: 10px;
  text-align: center;
}
</style>
